package itsm.isperp.framework.sequence;

import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.sequence.rule.SequenceRuleBuilder;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
import org.springframework.stereotype.Component;

/**
 * 实现{@link DataFieldMaxValueIncrementer}的一个流水号增值器。通过抽象的 {@link #getNextKey}
 * 模板方法返回一个指定的long形键值，并通过规则解析器返回最终结果
 * 
 * @author lizx
 * @date 2013-3-6
 */
@Component
public class SequenceIncrementer implements InitializingBean {

	/**
	 * 一个流水号服务类
	 */
	@Autowired
	protected SequenceService sequenceService;

	/**
	 * 流水号应用的表名
	 */
	protected String tableName;

	/**
	 * 默认的构造器，用于bean风格使用。
	 * 
	 */
	public SequenceIncrementer() {
	}

	// /**
	// * 简便的构造器
	// *
	// * @param service
	// * 序列号服务
	// * @param tableName
	// * 需要进行序列号赋值的表名称
	// */
	// public SequenceIncrementer(SequenceService service, String tableName) {
	// this.sequenceService = service;
	// this.tableName = tableName;
	// }

	public String nextStringValue() {

		// 此处优化为缓存模式
		SequenceRule rule = ContextHolder.getApplicationSequenceCache().get(
				tableName);

		// 判断是否需要重置

		long key = getNextKey(rule.getSeqResetType());

		return SequenceRuleBuilder.getPrefix(rule.getSeqRule())
				+ SequenceRuleBuilder.getFormatedNumber(rule.getSeqRule(), key);
	}

	/**
	 * 下一个流水号的数字
	 * 
	 * @return 一个long型的流水键。它将通过不同子类实现形成一个公共的具体的方法。
	 */
	protected long getNextKey(Integer seqResetType) {
		return this.sequenceService.nextNumber(tableName, seqResetType);
	}

	public SequenceService getSequenceService() {
		return sequenceService;
	}

	public String getTableName() {
		return tableName;
	}

	public void setSequenceService(SequenceService sequenceService) {
		this.sequenceService = sequenceService;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public int nextIntValue(Integer seqResetType) {
		return (int) getNextKey(seqResetType);
	}

	public long nextLongValue(Integer seqResetType) {

		return getNextKey(seqResetType);
	}

	public void afterPropertiesSet() {
		if (this.sequenceService == null) {
			throw new IllegalArgumentException(
					"Property 'sequenceService' is required");
		}

	}

}
